package graphics;

import entities.Builder;
import entities.Diamond;
import entities.Entity;
import entities.Gas;
import entities.Tile;
import java.awt.Image;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import javax.swing.ImageIcon;
import willispace.Config;
import willispace.Database;
import willispace.Map;

/**
 * Manager of resources (maps, images)
 * @author mateusz
 */
public class ResourcesManager {

    private HashMap<String, Image> images;
    private final String[] imagesList = { "transporter", "factory", "worker",
                                          "builder", "tile", "rock", "diamond",
                                          "gas", "gasInFlames" };

    /**
     * Creates new Manager of Resources
     */
    public ResourcesManager() {
        // initialization
        images = new HashMap<String, Image>();
        
        // load images from list
        loadImages();
    }

    /**
     * Returns an image object represented by name
     * @param name  name of image (path in images directory, without extension)
     * @return  the image with specified name
     */
    public Image get( String name ) {
        return images.get( name );
    }

    /**
     * loads all images from imagesList
     */
    private void loadImages() {
        Image img;
        for ( String imagePath : imagesList ) {
            img = loadImage( imagePath );
            images.put( imagePath, img );
        }

    }

    /**
     * load single image with specified name
     * @param name  name of image (path in images directory, without extension)
     * @return  the image with specified name
     */
    public static Image loadImage( String name ) {
        String filename = "images/" + name + ".png";
        return new ImageIcon( filename ).getImage();
    }

    /**
     * Loads map from file
     * @param mapName   name of map (path)
     * @return {@link Map} map object created from specified map
     * @throws IOException when error occured during map reading
     */
    public Map loadMap( String mapName )
            throws IOException {
        ArrayList lines = new ArrayList();
        int width = 0;
        int height = 0;

        // read all rows to list
        BufferedReader reader = new BufferedReader(
                new FileReader( mapName ) );
        while ( true ) {
            String line = reader.readLine();
            // end of rows to read
            if ( line == null ) {
                reader.close();
                break;
            }

            lines.add( line );
            width = Math.max( width, line.length() );
        }

        // rows analysis
        height = lines.size();
        Map newMap = new Map( width, height );

        // update config
        Config.verticalTiles = Math.min( Config.verticalTiles, height );
        Config.horizontalTiles = Math.min( Config.horizontalTiles, width );

        for ( int y = 0; y < height; y++ ) {
            String line = ( String ) lines.get( y );
            for ( int x = 0; x < line.length(); x++ ) {
                char ch = line.charAt( x );
                boolean block = false;
                Entity e = null;
                
                // add tile
                if ( ch == '#' ) {
                    newMap.setTile( x, y, true, get( "rock" ));
                }
                else {
                    newMap.setTile( x, y, block, get( "tile" ));
                }
                
                Tile tile = newMap.getTile(x, y);
                
                // add entity
                if ( ch == 'B' ) {
                    Database.builder = new Builder( tile, get( "builder" ), "builder");
                }
                else if ( ch == 'G' ) {
                    e = new Gas( tile, get( "gas" ), get("gasInFlames"), "gas"+Integer.toString(Database.gases.size()));
                    Database.gases.add((Gas) e );
                    block = true;
                }
                else if ( ch == 'D' ) {
                    e = new Diamond( tile , get( "diamond" ), "diamond"+Integer.toString(Database.diamonds.size())); 
                    Database.diamonds.add( (Diamond) e);
                    block = true;
                }

                tile.associateWithEntity(e);
                
            }

            // fill rest of line
            for ( int x = line.length(); x < width; x++ ) {
                newMap.setTile( x, y, false, get( "tile" ), null);
            }
        }
        
        return newMap;
    }
    
}
